package com.shop.shopserver.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.shop.shopcommon.context.SecurityContext;
import com.shop.shoppojo.dto.HomeDataDTO;
import com.shop.shoppojo.entity.*;
import com.shop.shoppojo.vo.GoodsDetailVO;
import com.shop.shoppojo.vo.HomeDataItemsVO;
import com.shop.shoppojo.vo.HomeDataVO;
import com.shop.shopserver.filter.HierarchicalBloomFilter;
import com.shop.shopserver.mapper.*;
import com.shop.shopserver.redis.RedisCacheOperate;
import com.shop.shopserver.service.GoodsService;
import com.shop.shopserver.service.SearchService;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptType;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.ScriptSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.shop.shopcommon.constant.ElasticSearchConstant.*;

@Service
@Slf4j
public class GoodsServiceImpl implements GoodsService {
    @Autowired
    private GoodsMapper goodsMapper;

    @Autowired
    private GoodsImagesMapper goodsImagesMapper;


    @Autowired
    private BannerMapper bannerMapper;
    @Autowired
    private NavBarMapper navBarMapper;
    @Autowired
    private SearchService searchService;
    @Autowired
    private RestHighLevelClient client;
    @Autowired
    private HotSearchMapper hotSearchMapper;
    @Autowired
    private RedisCacheOperate redisCacheOperate;
    @Autowired
    private HierarchicalBloomFilter bloomFilter;
    public GoodsDetailVO getGoodsDetailByGoodsId(Long goodsId){
        /**
         * 根据goodsId查询商品详情
         */
//        LambdaQueryWrapper<GoodsImages> goodsimagesLambdaQueryWrapper = new LambdaQueryWrapper<GoodsImages>()
//                .eq(GoodsImages::getGoodsId,goodsId);
//        List<GoodsImages> goodsImages=goodsImagesMapper.selectList(goodsimagesLambdaQueryWrapper);
//        LambdaQueryWrapper<Goods> goodsLambdaQueryWrapper = new LambdaQueryWrapper<Goods>()
//                .eq(Goods::getId,goodsId);
//        List<Goods> goods =goodsMapper.selectList(goodsLambdaQueryWrapper);
        log.info("开始查询Goods对象，查询条件为goodsId: {}", goodsId);
        //查询商品信息
//        Goods firstgoods =goods.get(0) ;


        // 配置了布隆过滤器
        if (!bloomFilter.contains(goodsId.toString())){
            return null;
        }
        // 配置Redis缓存和防击穿、缓存重建的商品查询
        Goods firstgoods = redisCacheOperate.getDataFromRedis(goodsId);

        if (firstgoods == null){
            return null;
        }

        List<Goods> goods = new ArrayList<>();
        goods.add(firstgoods);

        // 查询商品图片信息
        LambdaQueryWrapper<GoodsImages> goodsimagesLambdaQueryWrapper = new LambdaQueryWrapper<GoodsImages>()
                .eq(GoodsImages::getGoodsId,goodsId);
        List<GoodsImages> goodsImages=goodsImagesMapper.selectList(goodsimagesLambdaQueryWrapper);

        GoodsDetailVO goodsDetailVO = GoodsDetailVO
                .builder()
                .id(firstgoods.getId())
                .goodsName(firstgoods.getGoodsName())
                .goodsImage(firstgoods.getGoodsImage())
                .goodsPriceMin(firstgoods.getGoodsPriceMin())
                .goodsPriceMax(firstgoods.getGoodsPriceMax())
                .stockTotal(firstgoods.getStockTotal())
                .goodsSales(firstgoods.getGoodsSales())
                .build();

        if(goodsDetailVO ==null){
            log.error("goodsDetailVO不能为空");
            return null;
        }
        goodsDetailVO.setGoodsImages(goodsImages);
        goodsDetailVO.setSkuList(goods);
        //将图片和商品参数注入到detail中
        return goodsDetailVO;
    }

    /**
     * 获取首页数据
     * @return
     * @throws Exception
     */
    @Override
    public HomeDataVO getHomeData() throws Exception {
        // 获取轮播图数据
        List<Banner> banners = bannerMapper.selectList(null);
        HomeDataDTO bannerData = HomeDataDTO.builder()
                .name("图片轮播")
                .data(banners)
                .type("banner")
                .build();

        // 获取导航组数据
        List<NavBar> navBars = navBarMapper.selectList(null);
        HomeDataDTO navBarData = HomeDataDTO.builder()
                .name("导航组")
                .data(navBars)
                .type("navBar")
                .build();

        // 获取猜你喜欢商品数据
        String searchWords="";
        // 1.获取热门搜索词
        List<HotSearch> hotSearches = hotSearchMapper.selectList(null);
        // 2.使用 Stream 流拼接 text 字段值为字符串
        String result = hotSearches.stream()
                .map(HotSearch::getText)
                .collect(Collectors.joining());
        searchWords=result;

        // 3.判断用户是否登录 登陆则获取用户最近搜索词+热门搜索词 未登陆则获取热门搜索词
        if (SecurityContext.getUsername()!=null){
            // 用户已登录 获取用户最近搜索词
            String topUserSearchWord = searchService.getTopUserSearchWord();
            // 拼接到searchWords
            searchWords+=topUserSearchWord;
        }

        // 4.根据最终搜索词查询商品数据
        log.info("最终搜索词条字符串："+searchWords);
        List<Goods> userSearchGoodsData = getUserSearchGoodsData(searchWords);

        // 5.将数据封装到HomeDataVO中
        HomeDataDTO goodsData = HomeDataDTO.builder()
                .name("商品组")
                .goodsData(userSearchGoodsData)
                .type("goods")
                .build();

        // 封装数据返回
        ArrayList<HomeDataDTO> items = new ArrayList<>();
        items.add(bannerData);
        items.add(navBarData);
        items.add(goodsData);
        return new HomeDataVO(new HomeDataItemsVO(items));
    }

    /**
     * 获取词条相关的商品数据
     * @throws Exception
     */
    public List<Goods> getUserSearchGoodsData(String searchWord) throws Exception{
        // 商品列表
        List<Goods> goods = new ArrayList<>();
        try {
            // 创建搜索请求
            SearchRequest searchRequest = new SearchRequest(GOODS_INDEX_NAME);

            // 构建查询条件
            MatchQueryBuilder matchQuery = QueryBuilders.matchQuery(GOODS_NAME_FIELD, searchWord)
                    .analyzer(IK_MAX_WORD);

            // 构建随机排序脚本
            Map<String, Object> params = new HashMap<>();
            Script script = new Script(ScriptType.INLINE, "painless", "Math.random()", params);
            ScriptSortBuilder scriptSortBuilder = new ScriptSortBuilder(script, ScriptSortBuilder.ScriptSortType.NUMBER)
                    .order(SortOrder.ASC);

            // 构建搜索源
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
                    .query(matchQuery)
                    .sort(scriptSortBuilder)
                    .size(SELECT_HISTORY_NUM);

            // 设置搜索源到搜索请求
            searchRequest.source(searchSourceBuilder);

            // 执行搜索请求
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

            // 处理搜索结果
            SearchHit[] searchHits = searchResponse.getHits().getHits();
            for (SearchHit hit : searchHits) {
                System.out.println(hit.getSourceAsString());
                goods.add(JSON.parseObject(hit.getSourceAsString(), Goods.class));
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        return goods;
    }

}
